import 'dart:convert';
import 'dart:developer';
import 'dart:io';

import 'package:ball_lion/server/http/rsa_util.dart';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:ball_lion/entity/other/image_upload_result_entity.dart';
import 'package:ball_lion/server/http/request_header.dart';
import 'package:ball_lion/server/http/request_interceptor.dart';
import 'package:ball_lion/utils/app_config.dart';
import 'package:ball_lion/utils/constant.dart';
import 'package:ball_lion/utils/sp_utils.dart';
import 'package:ball_lion/utils/toast_utils.dart';
import 'error_interceptor.dart';
import 'log.dart';

class DioUtils {
  static int timeoutDuration = 15;
  static final baseUrl =
      (AppConfig.config.isDebug) ? SpUtils.baseUrl : Constant.prodBaseUrl;
  static final options = BaseOptions(
      followRedirects: false,
      connectTimeout: Duration(seconds: timeoutDuration),
      receiveTimeout: Duration(seconds: timeoutDuration),
      sendTimeout: Duration(seconds: timeoutDuration),
      responseType: ResponseType.json,
      baseUrl: baseUrl);
  static bool hasNetwork = true;
  static Dio dio = () {
    final dio = Dio(options)
      ..interceptors.add(ErrorInterceptor())
      ..interceptors.add(RequestInterceptor());
    (dio.httpClientAdapter as IOHttpClientAdapter).createHttpClient = () {
      final client = HttpClient();
      client.badCertificateCallback = (cert, host, port) => true;
      if (AppConfig.config.isDebug && SpUtils.proxyEnabled) {
        client.findProxy = (uri) {
          return 'PROXY ${SpUtils.proxyUrl}';
        };
      }

      return client;
    };
    return dio;
  }.call();

  static Future<Response> post(String url,
      {dynamic params,
      bool showLoading = false,
      int? receiveTimeout,
      bool needEncrypt = true,
      bool showToast = true}) async {
    if (showLoading) {
      EasyLoading.show();
    }
    try {
      dioLog.d('Dio request for url:$url  params:$params');
      if (params != Null && needEncrypt) {
        params = wrapParams(params, url);
      }
      Options? option;
      if (receiveTimeout != null) {
        option = Options(receiveTimeout: Duration(seconds: receiveTimeout));
      }
      Response response =
          await dio.post('/h5/qiushi/api', data: params, options: option);
      if (RequestHeader.env.length == 0) {
        RequestHeader.env =
            (response.headers.map['env']?.first as String?) ?? "";
      }
      if (kDebugMode) {
        String? traceId = response.headers.value("traceid");
        dioLog.d('Dio response for $url\n Traceid:$traceId\n');
        log('${response.data}');
      }
      if (showLoading) {
        EasyLoading.dismiss();
      }
      String? toast = response.data['t'];
      if (toast != null && showToast) {
        if (toast.isNotEmpty) {
          Toast.text(toast);
        }
      }

      return response;
    } finally {
      // Loading.hideLoading(context);
    }
  }

  static Future<List<ImageUploadResultEntity>?> uploadImage(
      List<String> files, String path,
      {int? width, int? height}) async {
    EasyLoading.show();
    try {
      final filesData = [];
      for (final file in files) {
        final data = await MultipartFile.fromFile(file);
        filesData.add(data);
      }
      FormData data = FormData.fromMap({
        'path': path,
        'files': filesData,
      });
      Response result =
          await dio.post('/resource/rse-img-do/uploads', data: data);
      dioLog.d('upload image $result');
      EasyLoading.dismiss();
      final toast = result.data['t'];
      if (toast != null) {
        Toast.text(toast);
      }
      if (result.statusCode == 200 && result.data['c'] == 200) {
        List<ImageUploadResultEntity> data = result.data['d']
            .map<ImageUploadResultEntity>(
                (e) => ImageUploadResultEntity.fromJson(e))
            .toList();
        return data;
      }

      return null;
    } finally {
      // Loading.hideLoading(context);
    }
  }

  static Map<String, dynamic> wrapParams(dynamic params, String uri) {
    try {
      Map<String, dynamic> m = {'uri': uri};
      Map<String, dynamic> d = {};
      if (params == null) {
      } else {
        if (params is Map<String, dynamic> || params is String) {
          d['d'] = params;
        } else {
          d['d'] = "$params";
        }
      }
      m['d'] = d;
      String mStr = jsonEncode(m);
      //dioLog.d(RsaUtil.encryptText(mStr));
      return {"m": RsaUtil.encryptText(mStr)};
    } catch (err) {
      dioLog.d('$err');
    }

    var param = {
      'd': {'d': params},
      'uri': uri
    };
    return param;
  }
}
